//
//  BZThemeManager.m
//  MZBasic
//
//  Created by Sings on 2022/8/10.
//

#import "BZThemeManager.h"
#import "BZThemeModel.h"
#import <objc/message.h>
#import "NSObject+BZTheme.h"
#import "BaseRegisterModel.h"
#import "BZThemeConfigModel.h"

#define BZTHEME_CONFIGPATH                                                                                   \
[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]  \
stringByAppendingPathComponent:@"BZTHEMECONFIG.archive"]

@interface BZThemeManager ()

@property (nonatomic, strong) NSHashTable *haThemeModel;

@end

@implementation BZThemeManager

static BZThemeManager *_themeManger = nil;

void BZThemeBlock(id target,BZThemeBindBlock block){
    [[BZThemeManager sharedInstance] bindBlockWithTarget:target Block:block];
}

NSString* BZThemeKeyToStr(NSString *key) {
    SEL sel = @selector(valueForKey:);
    return ((NSString * (*)(id, SEL, NSString *))(void *) objc_msgSend)((id)[BaseRegisterModel sharedInstance].mdicThemeColorRouting, sel, key);
}

NSString* BZThemeFilePath(void) {
    return [BaseRegisterModel sharedInstance].strThemeFilePath;
}

+ (void)load {
    [[self sharedInstance] config];
}

+ (instancetype) sharedInstance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _themeManger = [[super allocWithZone:NULL] init];
    });
    
    return _themeManger;
}

- (void) config {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSFileManager *manager = [NSFileManager defaultManager];
        BOOL isfile = [manager fileExistsAtPath:BZTHEME_CONFIGPATH];
        if (isfile) {
            BZThemeConfigModel *themeModel = [NSKeyedUnarchiver unarchiveObjectWithFile:BZTHEME_CONFIGPATH];
            id<BZThemeExampleProtocol> themeExample = [[NSClassFromString(themeModel.strClass) alloc] initThemeWithThemeVersion:themeModel.themeVersion];
            [self switchTheme:themeExample Finished:nil];
        }else {
            [self switchTheme:[[BZThemeDefaultExample alloc] init] Finished:nil];
        }
    });
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    return [BZThemeManager sharedInstance];
}

- (id)mutableCopy {
    return _themeManger;
}

- (id)copy {
    return _themeManger;
}

- (NSHashTable *) haThemeModel {
    if (_haThemeModel == nil) {
        _haThemeModel = [NSHashTable weakObjectsHashTable];
    }
    return _haThemeModel;
}

- (void) bindColorWithTarget:(id) target KeyPath:(NSString *) keyPath ToKey:(NSString *) key {
    BZThemeModel *themeModel = [[BZThemeModel alloc] initColorWithTarget:target KeyPath:keyPath ColorKey:key];
    [self bindThemeModel:themeModel];
}

- (void) bindCGColorWithTarget:(id) target KeyPath:(NSString *) keyPath ToKey:(NSString *) key {
    BZThemeModel *themeModel = [[BZThemeModel alloc] initCGColorWithTarget:target KeyPath:keyPath ColorKey:key];
    [self bindThemeModel:themeModel];
}

- (void) bindColorWithTarget:(id) target KeyPath:(NSString *) keyPath ToColorPath:(NSString *) colorPath{
    BZThemeModel *themeModel = [[BZThemeModel alloc] initColorWithTarget:target KeyPath:keyPath ColorPath:colorPath];
    [self bindThemeModel:themeModel];
}

- (void) bindCGColorWithTarget:(id) target KeyPath:(NSString *) keyPath ToColorPath:(NSString *) colorPath {
    BZThemeModel *themeModel = [[BZThemeModel alloc] initCGColorWithTarget:target KeyPath:keyPath ColorPath:colorPath];
    [self bindThemeModel:themeModel];
}

- (void) bindImageWithTarget:(id) target KeyPath:(NSString *) keyPath ToKey:(NSString *) key {
    BZThemeModel *themeModel = [[BZThemeModel alloc] initImageWithTarget:target KeyPath:keyPath ImageKey:key];
    [self bindThemeModel:themeModel];
}

- (void) bindBlockWithTarget:(id) target Block:(BZThemeBindBlock) block {
    BZThemeModel *themeModel = [[BZThemeModel alloc] initBlockWithTarget:target Block:block];
    [self bindThemeModel:themeModel];
}

- (void) bindSelWithTarget:(id) target Sel:(SEL) sel {
    BZThemeModel *themeModel = [[BZThemeModel alloc] initSelWithTarget:target Sel:sel];
    [self bindThemeModel:themeModel];
}

- (void) bindThemeModel:(BZThemeModel *) themeModel {
    [themeModel refresh];
    NSMutableSet *msetTheme = [NSMutableSet setWithSet:[themeModel.target msetTheme]];
    if (msetTheme == nil) {
        msetTheme = [NSMutableSet set];
    }
    for (BZThemeModel *oldThemeModel in msetTheme) {
        if ([oldThemeModel.keyPath isEqualToString:themeModel.keyPath] && oldThemeModel.type == themeModel.type) {
            [msetTheme removeObject:oldThemeModel];
            break;
        }
    }
    [msetTheme addObject:themeModel];
    [themeModel.target setMsetTheme:msetTheme];
    [self.haThemeModel addObject:themeModel.target];
}

- (void) switchTheme:(id<BZThemeExampleProtocol>) theme Finished:(void (^) (BOOL isSuccess, NSString *strError)) finished {
    BZThemeConfigModel *configModel = [[BZThemeConfigModel alloc] init];
    configModel.themeVersion = [theme themeVersion];
    configModel.strClass = NSStringFromClass([theme class]);
    [NSKeyedArchiver archiveRootObject:configModel toFile:BZTHEME_CONFIGPATH];
    [[BaseRegisterModel sharedInstance] registerThemeFilePath:[theme themeImagePath]];
    [[BaseRegisterModel sharedInstance] registerThemeColorRouting:[NSMutableDictionary dictionaryWithDictionary:[theme themeExampleJson]]];
    [self refresh];
    if (finished) {
        finished(YES,@"");
    }
}

- (void) refresh {
//    dispatch_queue_t queue = dispatch_queue_create("ThemeRefresh", DISPATCH_QUEUE_SERIAL);
//    dispatch_async(queue, ^{
        for (id target in self.haThemeModel) {
            NSMutableSet *msetTheme = [NSMutableSet setWithSet:[target msetTheme]];
            for (BZThemeModel *themeModel in msetTheme) {
                [themeModel refresh];
            }
        }
//    });
}


@end
